package cj.primariaiquest.integration.endpoints;

import java.util.concurrent.TimeUnit;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.integration.channel.QueueChannel;

import cj.primariaiquest.commons.ApplicationContextHolder;

/**
 * This class is used to monitor a channel. If the channel's capacity gets below
 * a certain threshold the a new consumer will be created for that channel.
 * 
 * @author georgian.parvu
 * 
 */
public class ChannelBalanceHandler implements Runnable {
    private static Logger logger = Logger
	    .getLogger(ChannelBalanceHandler.class);
    private final QueueChannel monitoredChannel;
    private final long threshold;
    private ApplicationContextHolder appContext;
    private final Object desk;

    /**
     * General constructor. This class will monitor the given channel. If the
     * channel's capacity gets below the threshold the a new consumer will be
     * created for this channel.
     * 
     * @param monitoredChannel
     *            QueueChannel to be monitored
     * @param threshold
     *            minimum channel's capacity
     * @param appContext
     *            ApplicationContextHolder used to register the new bean
     * @param desk
     *            Any object that represents a consumer for a QueueChannel
     */
    public ChannelBalanceHandler(QueueChannel monitoredChannel, long threshold,
	    ApplicationContextHolder appContext, Object desk) {
	this.monitoredChannel = monitoredChannel;
	this.threshold = threshold;
	this.appContext = appContext;
	this.desk = desk;

	new Thread(this).start();
    }

    @Override
    public void run() {
	// constantly check the channel's capacity
	while (true) {
	    if (monitoredChannel.getRemainingCapacity() < threshold) {

		System.out.println(monitoredChannel.getComponentName()
			+ " capacitate ramasa "
			+ monitoredChannel.getRemainingCapacity());

		// create new consumer bean and register it
		BeanDefinitionRegistry registry = ((BeanDefinitionRegistry) appContext
			.getFactory());

		GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
		beanDefinition.setBeanClass(desk.getClass());
		beanDefinition.setLazyInit(false);
		beanDefinition.setAbstract(false);
		beanDefinition.setAutowireCandidate(true);
		beanDefinition.setScope("session");

		registry.registerBeanDefinition("AlimentationDesk"
			+ AlimentationDesk.count.getAndAdd(1), beanDefinition);

		try {
		    TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
		    e.printStackTrace();
		    logger.error(e);
		}
	    }
	}

    }
}
